
package net.swa.dewei.web.action;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.swa.dewei.beans.entity.WeixinInfo;
import net.swa.dewei.beans.entity.WxDateReport;
import net.swa.dewei.beans.vo.ReportWxDate;
import net.swa.dewei.beans.vo.WeixinStatis;
import net.swa.dewei.service.WeixinInfoService;
import net.swa.dewei.thread.QueryWxInfoThread;
import net.swa.system.service.ICommonService;
import net.swa.system.util.annotation.Log;
import net.swa.system.web.action.AbstractBaseAction;
import net.swa.util.BuzConst;
import net.swa.util.DateUtils;
import net.swa.util.JsonResult;
import net.swa.util.MySecureProtocolSocketFactory;

/** 微信信息表 Action **/
public class WeixinInfoAction extends AbstractBaseAction
{
    private static final long serialVersionUID = 1908627223355967719L;

    private final Logger log = Logger.getLogger(WeixinInfoAction.class);

    private WeixinInfoService weixinInfoService;

    private WeixinInfo model;

    // 实体类id
    private String id;

    // 批量删除的id集合
    private String[] ids;

    private String nickname;

    private String oldWxid;

    //微信id
    private String wxid;

    private String sdate;

    private String edate;

    private String keyType;

    private String reportJson;

    /** 公用方法接口 */
    private ICommonService commonService;

    private WeixinStatis bean;

    @Required
    @Resource
    public void setCommonService(ICommonService commonService)
    {
        this.commonService = commonService;
    }

    /** 初始化分页查询 **/
    @Log(description = "初始化微信号分页查询")
    public String listPage()
    {
        return "listPage";
    }

    @Log(description = "去微信号编辑页面")
    public String toEdit()
    {
        if (!StringUtils.isBlank(id))
        {
            model = weixinInfoService.queryById(id);
        }
        else
        {
            model = new WeixinInfo();
        }
        return "toEdit";
    }

    @Log(description = "保存微信信息")
    public String saveWxInfo() throws Exception
    {
        if (null != model)
        {
            weixinInfoService.saveModel(model);
            outSuccess();
        }
        else
        {
            outError("error");
        }
        return null;
    }

    /**
     * 更新关注公众号的用户信息
     * 
     * @throws Exception
     **/
    @Log(description = "更新关注公众号的用户信息")
    public String tongbu() throws Exception
    {

        if (QueryWxInfoThread.hasThreadRunning())
        {
            outError("已经有用户正在执行同步");
        }
        else
        {
            // 将完成同步的记录数置0
            QueryWxInfoThread.setC(0);
            String token = getToken();
            if (tongbu(token, ""))
            {
                while (true)
                {// 等待所有子线程执行完
                    if (!QueryWxInfoThread.hasThreadRunning())
                    {
                        break;
                    }
                    Thread.sleep(500);
                }
                outSuccess();
            }
            else
            {
                outError("同步信息出现异常，请重试");
            }
        }
        return null;
    }

    private boolean tongbu(final String token , String next_openid) throws Exception
    {
        if (log.isDebugEnabled())
        {
            log.debug("开始更新   token 为：" + token);
        }
        String http = BuzConst.HTTP_WX_USER_LIST + "?access_token=" + token + "&next_openid=" + next_openid;
        String resp = MySecureProtocolSocketFactory.get(http);
        JSONObject jsonObj = JSONObject.fromObject(resp.toString());
        Object errcode = (Object) jsonObj.get("errcode");
        if (null != errcode)
        {
            // 如果错误码不为空
            if (log.isDebugEnabled())
            {
                log.debug("错误码为：" + errcode);
            }
            removeSessionAttribute(BuzConst.TOKEN);
            return false;
        }
        else
        {
            int total = (Integer) jsonObj.get("total");
            int count = (Integer) jsonObj.get("count");
            String nexOpenid = (String) jsonObj.get("next_openid");
            JSONObject data = jsonObj.getJSONObject("data");
            JSONArray array = data.getJSONArray("openid");
            if (null != array)
            {
                // List<WeixinInfo> list = new ArrayList<WeixinInfo>();
                Iterator<?> it = array.iterator();

                ExecutorService pool = Executors.newFixedThreadPool(BuzConst.NUM_THREAD);
                while (it.hasNext())
                {

                    final String openId = (String) it.next();

                    final QueryWxInfoThread qu = new QueryWxInfoThread(token, openId, weixinInfoService, total);
                    // 创建实现了Runnable接口对象，Thread对象当然也实现了Runnable接口
                    pool.execute(qu);

                    // list.add(setOtherInfoAndSave(token, openId));
                    // if (0 == (c + 1) % 100)
                    // {
                    // weixinInfoService.batchUpdate(list);
                    // list.clear();
                    // }
                    // c++;
                    // setSessionAttribute(Const.CURRENT_PROCESS, 100 *c /
                    // total);
                }
            }
            if (total > count && count > 0 && (!StringUtils.isBlank(nexOpenid)))
            {
                tongbu(token, nexOpenid);
            }
        }
        return true;
    }

    /***
     * 查询进度
     * 
     * @return
     * @throws Exception
     */
    public String queryProcess() throws Exception
    {
        Map<String, Object> map = new HashMap<String, Object>();
        if (QueryWxInfoThread.getProcess() > 0)
        {
            map.put("success", true);
            map.put("process", QueryWxInfoThread.getProcess());
        }
        else
        {
            map.put("success", false);
            map.put("message", "进度未知");
        }
        outJson(map);
        return null;
    }

    // 该部分已经多线程实现
    // private WeixinInfo setOtherInfoAndSave(String token , String openId)
    // throws Exception
    // {
    // WeixinInfo wx = new WeixinInfo();
    // wx.setId(openId);
    // String nickname = null;
    // String http =Const.HTTP_WX_USER_INFO+ "?access_token=" + token +
    // "&openid=" + openId;
    // String resp = MySecureProtocolSocketFactory.get(http);
    // JSONObject jsonObj = JSONObject.fromObject(resp.toString());
    // if (null != jsonObj)
    // {
    // if (null != jsonObj.get("nickname"))
    // {
    // nickname = jsonObj.get("nickname").toString();
    // nickname = StringUtil.filterStr(nickname);
    // wx.setNickname(nickname);
    // }
    // if (null != jsonObj.get("province"))
    // {
    // String province = jsonObj.get("province").toString();
    //
    // wx.setProvince(province);
    // }
    //
    // if (null != jsonObj.get("city"))
    // {
    // String city = jsonObj.get("city").toString();
    // wx.setCity(city);
    // }
    //
    // if (null != jsonObj.get("headimgurl"))
    // {
    // String headimgurl = jsonObj.get("headimgurl").toString();
    // wx.setHeadimgurl(headimgurl);
    // if (headimgurl.length() > 0)
    // {
    // wx.setSheadimgurl("data:image/png;base64," +
    // FileUtil.imageToBase64(headimgurl.substring(0, headimgurl.length() - 1) +
    // "64"));
    // }
    // }
    //
    // if (null != jsonObj.get("subscribe"))
    // {
    // String subscribe = jsonObj.get("subscribe").toString();
    // wx.setSubscribe(subscribe);
    // }
    //
    // if (null != jsonObj.get("sex"))
    // {
    // String sex = jsonObj.get("sex").toString();
    // wx.setSex(sex);
    // }
    //
    // if (null != jsonObj.get("language"))
    // {
    // String language = jsonObj.get("language").toString();
    // wx.setLanguage(language);
    // }
    //
    // if (null != jsonObj.get("country"))
    // {
    // String country = jsonObj.get("country").toString();
    // wx.setCountry(country);
    // }
    // if (null != jsonObj.get("subscribe_time"))
    // {
    // String subscribe_time = jsonObj.get("subscribe_time").toString();
    // wx.setSubscribe_time(subscribe_time);
    // }
    // }
    // return wx;
    // }

    private String getToken() throws Exception
    {
        String token = (String) getSessionAttribute(BuzConst.TOKEN);
        if (null == token)
        {
            String resp = MySecureProtocolSocketFactory.get(BuzConst.HTTP_WX_TOKEN + "?grant_type=client_credential&appid=" + BuzConst.APPID + "&secret=" + BuzConst.SECRET);
            JSONObject jsonObj = JSONObject.fromObject(resp);
            token = (String) jsonObj.get("access_token");
            setSessionAttribute(BuzConst.TOKEN, token);
        }
        log.debug("get token is " + token);
        return token;
    }

    /** * 删除方法 **/
    @Log(description = "删除微信")
    public String delete() throws Exception
    {
        weixinInfoService.delete(ids);
        ids = null;
        outSuccess();
        return null;
    }

    // 根据条件查询微信号分页
    public String queryWeixinPage() throws Exception
    {
        currentPage = currentPage == 0 ? 1 : currentPage;
        pageSize = pageSize == 0 ? 20 : pageSize;
        JsonResult<WeixinInfo> json = null;
        nickname = nickname == null ? null : nickname.trim();
        json = weixinInfoService.queryWeixinPage(nickname, oldWxid, currentPage, pageSize);
        json.setCurrentPage(currentPage);
        outJson(json);
        return null;
    }

    /**关注时候调用接口，暂无校验**/
    public String guanzhu()
    {
        removeSessionAttribute(BuzConst.TOKEN);
        if (StringUtils.isBlank(wxid))
        {
            log.debug("增量同步action-----------传入的wxid 为空");
        }
        else
        {
            String token = null;
            try
            {
                token = getToken();
                log.debug("after  get token is " + token);
                weixinInfoService.saveOrUpdateModel(wxid, token, true);
            }
            catch (Exception e)
            {
                log.debug("增量同步action-----------或取token 异常" + e.toString());
                e.printStackTrace();
            }
        }
        return null;
    }

    /**取消关注时候调用接口，暂无校验**/
    public String quxiaoGuanzhu()
    {
        removeSessionAttribute(BuzConst.TOKEN);
        if (StringUtils.isBlank(wxid))
        {
            log.debug("增量同步action2-----------传入的wxid 为空");
        }
        else
        {
            String token = null;
            try
            {
                token = getToken();
                log.debug("after  get token is " + token);
                weixinInfoService.saveOrUpdateModel(wxid, token, false);
            }
            catch (Exception e)
            {
                log.debug("增量同步action2-----------或取token 异常");
                e.printStackTrace();
            }
        }
        return null;
    }

    /**微信用户统计**/
    public String statis()
    {
        sdate = DateUtils.getfirstDayOfThisMonth();
        edate = DateUtils.getCurrDate("yyyy-MM-dd");
        keyType="1";
        ReportWxDate report = weixinInfoService.queryDateReport(keyType, sdate, edate);

        reportJson = JSONObject.fromObject(report).toString();
        log.debug("粉丝统计：" + reportJson);
        bean = weixinInfoService.queryStatis();
        return "statis";
    }

    /**微信用户统计**/
    public String statisData()
    {
        if (StringUtils.isBlank(sdate) || StringUtils.isBlank(sdate))
        {
            sdate = DateUtils.getfirstDayOfThisMonth();
            edate = DateUtils.getCurrDate("yyyy-MM-dd");
            log.debug("ERROR:没有传入起始日期,按默认日期查询！");
        }
        ReportWxDate report = weixinInfoService.queryDateReport(keyType, sdate, edate);
        reportJson = JSONObject.fromObject(report).toString();
        log.debug("粉丝统计：" + reportJson);
        bean = weixinInfoService.queryStatis();
        return "statis";
    }
    
    /**分页查询
     * @throws Exception ***/
    public String queryWxReportPage() throws Exception{
        currentPage = currentPage == 0 ? 1 : currentPage;
        pageSize = pageSize == 0 ? 20 : pageSize;
        JsonResult<WxDateReport> json = null;
        //支持多种条件查询分页便于扩展
        json = weixinInfoService.queryWxReportPage(keyType, sdate, edate, currentPage, pageSize, orderBy, orderType);
        json.setCurrentPage(currentPage);
        outJson(json);
        return null;
    }

    public String queryStatis() throws Exception
    {
        bean = weixinInfoService.queryStatis();
        outJson(bean);
        return null;
    }

    public ICommonService getCommonService()
    {
        return commonService;
    }

    public WeixinInfoService getWeixinInfoService()
    {
        return weixinInfoService;
    }

    @Required
    @Resource
    public void setWeixinInfoService(WeixinInfoService weixinInfoService)
    {
        this.weixinInfoService = weixinInfoService;
    }

    public WeixinInfo getModel()
    {
        return model;
    }

    public void setModel(WeixinInfo model)
    {
        this.model = model;
    }

    public String getId()
    {
        return id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String[] getIds()
    {
        return ids;
    }

    public void setIds(String[] ids)
    {
        this.ids = ids;
    }

    public String getNickname()
    {
        return nickname;
    }

    public void setNickname(String nickname)
    {
        this.nickname = nickname;
    }

    public String getOldWxid()
    {
        return oldWxid;
    }

    public void setOldWxid(String oldWxid)
    {
        this.oldWxid = oldWxid;
    }

    public String getWxid()
    {
        return wxid;
    }

    public void setWxid(String wxid)
    {
        this.wxid = wxid;
    }

    public WeixinStatis getBean()
    {
        return bean;
    }

    public void setBean(WeixinStatis bean)
    {
        this.bean = bean;
    }

    public String getSdate()
    {
        return sdate;
    }

    public void setSdate(String sdate)
    {
        this.sdate = sdate;
    }

    public String getEdate()
    {
        return edate;
    }

    public void setEdate(String edate)
    {
        this.edate = edate;
    }

    public String getKeyType()
    {
        return keyType;
    }

    public void setKeyType(String keyType)
    {
        this.keyType = keyType;
    }

    public String getReportJson()
    {
        return reportJson;
    }

    public void setReportJson(String reportJson)
    {
        this.reportJson = reportJson;
    }
}
